<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Writing tests for Twisted code</title>
  </head>

  <body>

<h1>Writing tests for Twisted code</h1>

<h2>Trial basics</h2>

<p><strong>Trial</strong> is Twisted's testing framework.  It provides a
library for writing test cases and utility functions for working with the
Twisted environment in your tests, and a command-line utility for running your
tests. Trial is built on the Python standard library's <code>unittest</code>
module.</p>

<p>To run all the Twisted tests, do:</p>

<pre class="shell">
$ trial twisted
</pre>

<p>Refer to the Trial man page for other command-line options.</p>


<h2>Twisted-specific quirks: reactor, Deferreds, callLater</h2>

<p>The standard Python <code>unittest</code> framework, from which Trial is
derived, is ideal for testing code with a fairly linear flow of control.
Twisted is an asynchronous networking framework which provides a clean,
sensible way to establish functions that are run in response to events (like
timers and incoming data), which creates a highly non-linear flow of control.
Trial has a few extensions which help to test this kind of code. This section
provides some hints on how to use these extensions and how to best structure
your tests.</p>

<h3>Leave the Reactor as you found it</h3>

<p>Trial runs the entire test suite (over two thousand tests) in a single
process, with a single reactor. Therefore it is important that your test
leave the reactor in the same state as it found it. Leftover timers may
expire during somebody else's unsuspecting test. Leftover connection attempts
may complete (and fail) during a later test. These lead to intermittent
failures that wander from test to test and are very time-consuming to track
down.</p>

<p>Your test is responsible for cleaning up after itself. The
<code>tearDown</code> method is an ideal place for this cleanup code: it is
always run regardless of whether your test passes or fails (like a bare
<code>except</code> clause in a try-except construct). Exceptions in
<code>tearDown</code> are flagged as errors and flunk the test.</p>

<p>If your code uses Deferreds or depends on the reactor running, you can
return a Deferred from your test method, setUp, or tearDown and Trial will
do the right thing. That is, it will run the reactor for you until the
Deferred has triggered and its callbacks have been run. Don't use
<code>reactor.run()</code>, <code>reactor.stop()</code>, or
<code>reactor.iterate()</code> in your tests.</p>

<p>Calls to <code>reactor.callLater</code> create <code class="API"
base="twisted.internet.interfaces">IDelayedCall</code>s.  These need to be run
or cancelled during a test, otherwise they will outlive the test.  This would
be bad, because they could interfere with a later test, causing confusing
failures in unrelated tests!  For this reason, Trial checks the reactor to make
sure there are no leftover <code class="API"
base="twisted.internet.interfaces">IDelayedCall</code>s in the reactor after a
test, and will fail the test if there are.  The cleanest and simplest way to
make sure this all works is to return a Deferred from your test.</p>

<p>Similarly, sockets created during a test should be closed by the end of the
test.  This applies to both listening ports and client connections.  So, calls
to <code>reactor.listenTCP</code> (and <code>listenUNIX</code>, and so on)
return <code class="API"
base="twisted.internet.interfaces">IListeningPort</code>s, and these should be
cleaned up before a test ends by calling their <code class="API"
base="twisted.internet.interfaces.IListeningPort">stopListening</code> method.
Calls to <code>reactor.connectTCP</code> return <code class="API"
base="twisted.internet.interfaces">IConnector</code>s, which should be cleaned
up by calling their <code class="API"
base="twisted.internet.interfaces.IConnector">disconnect</code> method.  Trial
will warn about unclosed sockets.</p>

<p>The golden rule is: If your tests call a function which returns a Deferred,
your test should return a Deferred.</p>

<h3>Using Timers to Detect Failing Tests</h3>

<p>It is common for tests to establish some kind of fail-safe timeout that
will terminate the test in case something unexpected has happened and none of
the normal test-failure paths are followed. This timeout puts an upper bound
on the time that a test can consume, and prevents the entire test suite from
stalling because of a single test. This is especially important for the
Twisted test suite, because it is run automatically by the buildbot whenever
changes are committed to the Subversion repository.</p>

<p>The way to do this in Trial is to set the <code>.timeout</code> attribute
on your unit test method.  Set the attribute to the number of seconds you wish
to elapse before the test raises a timeout error.</p>


  </body>
</html>
